package com.yixing.tech.entity.entity.attr;

import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.base.ConditionsVO;
import com.yixing.tech.common.base.CustomAggregationOperation;
import com.yixing.tech.common.enums.YesOrNo;
import com.yixing.tech.entity.entity.RequestType;
import com.yixing.tech.common.utils.CommonUtil;
import com.yixing.tech.common.vo.s5.EntitySchema;
import com.yixing.tech.entity.service.EntityBaseService;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @author yixing tech
 * at 2021/10/9
 * describe：
 */
public class Dict extends AttrType {
    public Dict() {
        super("字典", "dict");
    }

    @Override
    public void out(List<AggregationOperation> operations, EntitySchema.AttrVO attr) throws BusinessException {
        super.out(operations, attr);
        Object reference = attr.getReference();
        String templateId = reference instanceof List ? ((List) reference).get(0).toString() : reference.toString();
        String relationalField = attr.getRelationalField();
        String sql;
        if (ObjectUtils.isEmpty(relationalField)) {
            sql = "{ $lookup:{ " +
                    "from:'dict'," +
                    "let:{ location_id:'$" + attr.getCode() + ".id'}," +
                    "pipeline:[" +
                    "{$match:{$expr:{$eq:['$_id','$$location_id']}}}," +
                    "{$project:{name:1,value:1,sort:1}}" +
                    "]," +
                    "as:'" + attr.getCode() + "'}}";
        } else {
            String condition = "{$expr:{$eq:['$" + relationalField + "','$$location_id']}}";
            String con;
            if (!CommonUtil.stringIsBlank(templateId)) {
                con = "{'$and':[{'parentId':'" + templateId + "'},";
                con += "{'isDelete':0},";
                con += condition;
                con += "]}";
            } else {
                con = condition;
            }
            sql = "{ $lookup:{ " +
                    "from:'dict'," +
                    "let:{ location_id:'$" + attr.getCode() + "'}," +
                    "pipeline:[" +
                    "{$match:" + con + "}," +
                    "{$project:{name:1,value:1,sort:1}}" +
                    "]," +
                    "as:'" + attr.getCode() + "'}}";
        }
        operations.add(new CustomAggregationOperation(sql));
        operations.add(Aggregation.unwind(attr.getCode(), true));
    }

    @Override
    public void out(List<AggregationOperation> operations, EntitySchema.AttrVO attr, RequestType requestType) throws BusinessException {
        out(operations, attr);
    }

    /**
     * 过滤条件处理
     *
     * @param cond
     * @param attr
     */
    @Override
    public void condition(ConditionsVO.Condition cond, EntitySchema.AttrVO attr) throws BusinessException {
        super.condition(cond, attr);
        if (CommonUtil.stringIsBlank(attr.getRelationalField()) && null != cond.getValue()) {
            cond.setKey(cond.getKey() + ".id");
            if ((cond.getValue() instanceof String)&&!ObjectId.isValid(cond.getValue().toString())) {
                throw new BusinessException(-1, "条件参数不能转为id");
            }
        }
    }

    /**
     * 值包装，不同属性类型的值需要进行包装，比如字典的名称或者编码会包装成字典对象
     *
     * @param attr
     * @param mongoTemplate
     * @return 默认返回原始值
     * @throws BusinessException
     */
    @Override
    public Object wrapValue(EntitySchema.AttrVO attr, Object value, MongoTemplate mongoTemplate, EntityBaseService objService, String tenantId) throws BusinessException {
        if (value == null) {
            return value;
        }
        if (!StringUtils.hasLength(value + "")) {
            return value;
        }

        Object reference = attr.getReference();
        // 字典应用
        String dictParentId = reference instanceof List ? ((List) reference).get(0).toString() : reference.toString();
        if (ObjectUtils.isEmpty(dictParentId)) {
            throw new BusinessException("未配置字典");
        }
        Document one = mongoTemplate.findOne(Query.query(Criteria.where("isDelete").ne(YesOrNo.YES.ordinal())
                .and("name").is(value).and("parentId").is(dictParentId)), Document.class, "dict");
        if (one == null) {
            throw new BusinessException(String.format("字典[%s]不存在", value));
        }
        return one;
    }
}
